package ThreadPool.lagou.concurrent.java并发编程78讲.生产者消费者模型;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @param
 * @author oyz
 * @version 1.0.4
 * @description: 生产者消费者模型
 * @date 2022/5/28 21:52
 */
public class MyBlockQueueForCondition<E> {
    /**
     * 定义一个队列
     */
    private Queue queue;
    /**
     *定义队列的大小
     */
    private int max = 16;

    /**
     * 定义锁
     */
    final ReentrantLock lock = new ReentrantLock();

    /**
     * 定义生产条件
     */
    final Condition productContion = lock.newCondition();

    /**
     * 定义消费条件
     */
    final Condition consumerContion = lock.newCondition();

    public MyBlockQueueForCondition(int size){
        this.max = size;
        queue = new LinkedList();
    }
    public MyBlockQueueForCondition(){

        queue = new LinkedList();
    }

    /**
     * 定义生产方法
     */
    public void put(E e) throws InterruptedException {
        //上锁
        lock.lock();
        try {
            // 这里用while而不用if是因为唤醒线程之后，是从await方法后执行，他不会重新判断一下if条件，如果是while他就会重新判断。
            // 再者唤醒线程的时机跟执行线程的时机不同，可能if里边的竞态条件发生了变化
            while (queue.size() == max) {
                productContion.await();
            }
            queue.add(e);
            // 唤醒消费者线程进行消费
            consumerContion.signalAll();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 定义消费者方法
     */
    public Object get() throws InterruptedException{
        lock.lock();
        try{
            while(max == 0){
                consumerContion.await();
            }
            Object remove = queue.remove();
            // 唤醒生产者线程进行生产
            productContion.signalAll();
            return remove;
        }finally {
            lock.unlock();
        }
    }



}
